﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Linq;
using Caffeine.Core.Test.TestModel;
using Caffeine.Core.Test.TestModel.PropertyRegistrations;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Caffeine.Core.Test
{
    [TestClass]
    public class ModelPropertyRegistrationTester
    {
        [TestMethod]
        public void ModelHasParentTest()
        {
            ModelForPropertyTesting viewModel = Creator.Create<ModelForPropertyTesting>();
            ModelWithNoProperties child = Creator.Create<ModelWithNoProperties>();

            Assert.IsFalse(child.HasParent);

            viewModel.ChildCollectionProperty1.Add(child);
            Assert.IsTrue(child.HasParent);

            viewModel.ChildCollectionProperty1.Clear();
            Assert.IsFalse(child.HasParent);

            viewModel.ChildCollectionProperty1.Add(child, true);
            Assert.IsTrue(child.HasParent);

            viewModel.ChildCollectionProperty1.Clear();
            Assert.IsTrue(child.HasParent);

            viewModel.ChildCollectionProperty1.Commit();
            Assert.IsFalse(child.HasParent);
        }

        [TestMethod]
        public void ModelWithNoPropertiesTest()
        {
            Creator.Create<ModelWithNoProperties>();
        }

        [TestMethod]
        public void ModelPropertyRegistrationTest()
        {
            ModelForPropertyTesting viewModel = Creator.Create<ModelForPropertyTesting>();

            String someValue = viewModel.StringProperty;
            Int32 someIntValue = viewModel.Int32Property;

            Assert.IsFalse(viewModel.ComputedStringProperty.IsWrapped);
            Assert.IsFalse(viewModel.ComputedStringProperty2.IsWrapped);
            Assert.IsFalse(viewModel.ComputedStringProperty3.IsWrapped);
            Assert.IsFalse(viewModel.ComputedStringProperty4.IsWrapped);
            Assert.IsFalse(viewModel.ComputedStringProperty5.IsWrapped);
            Assert.IsFalse(viewModel.ComputedStringProperty5.IsModelProperty);
            Assert.IsFalse(viewModel.ComputedStringProperty5.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.StringProperty.IsWrapped);
            Assert.IsFalse(viewModel.StringProperty.IsModelProperty);
            Assert.IsFalse(viewModel.StringProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.StringProperty2.IsWrapped);
            Assert.IsFalse(viewModel.StringProperty3.IsWrapped);
            Assert.IsFalse(viewModel.StringProperty4.IsWrapped);
            Assert.IsFalse(viewModel.StringProperty5.IsWrapped);
            Assert.IsFalse(viewModel.Int32Property.IsWrapped);
            Assert.IsFalse(viewModel.Int32Property.IsModelProperty);
            Assert.IsFalse(viewModel.Int32Property.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.Int32Property2.IsWrapped);
            Assert.IsFalse(viewModel.Int32Property3.IsWrapped);
            Assert.IsFalse(viewModel.Int32Property4.IsWrapped);
            Assert.IsFalse(viewModel.Int32Property5.IsWrapped);
            Assert.IsFalse(viewModel.NullableUInt32Property.IsWrapped);
            Assert.IsFalse(viewModel.NullableUInt32Property.IsModelProperty);
            Assert.IsFalse(viewModel.NullableUInt32Property.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.NullableUInt32Property2.IsWrapped);
            Assert.IsFalse(viewModel.NullableUInt32Property3.IsWrapped);
            Assert.IsFalse(viewModel.NullableUInt32Property4.IsWrapped);
            Assert.IsFalse(viewModel.NullableUInt32Property5.IsWrapped);
            Assert.IsFalse(viewModel.EnumProperty.IsWrapped);
            Assert.IsFalse(viewModel.EnumProperty.IsModelProperty);
            Assert.IsFalse(viewModel.EnumProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.EnumProperty2.IsWrapped);
            Assert.IsFalse(viewModel.EnumProperty3.IsWrapped);
            Assert.IsFalse(viewModel.EnumProperty4.IsWrapped);
            Assert.IsFalse(viewModel.EnumProperty5.IsWrapped);
            Assert.IsFalse(viewModel.NullableEnumProperty.IsWrapped);
            Assert.IsFalse(viewModel.NullableEnumProperty.IsModelProperty);
            Assert.IsFalse(viewModel.NullableEnumProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.NullableEnumProperty2.IsWrapped);
            Assert.IsFalse(viewModel.NullableEnumProperty3.IsWrapped);
            Assert.IsFalse(viewModel.NullableEnumProperty4.IsWrapped);
            Assert.IsFalse(viewModel.NullableEnumProperty5.IsWrapped);
            Assert.IsFalse(viewModel.StringArrayProperty.IsWrapped);
            Assert.IsFalse(viewModel.StringArrayProperty.IsModelProperty);
            Assert.IsFalse(viewModel.StringArrayProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.StringArrayProperty2.IsWrapped);
            Assert.IsFalse(viewModel.StringArrayProperty3.IsWrapped);
            Assert.IsFalse(viewModel.StringArrayProperty4.IsWrapped);
            Assert.IsFalse(viewModel.StringArrayProperty5.IsWrapped);
            Assert.IsFalse(viewModel.EnumerableProperty.IsWrapped);
            Assert.IsFalse(viewModel.EnumerableProperty.IsModelProperty);
            Assert.IsFalse(viewModel.EnumerableProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.EnumerableProperty2.IsWrapped);
            Assert.IsFalse(viewModel.EnumerableProperty3.IsWrapped);
            Assert.IsFalse(viewModel.EnumerableProperty4.IsWrapped);
            Assert.IsFalse(viewModel.EnumerableProperty5.IsWrapped);
            Assert.IsFalse(viewModel.ChildModelProperty.IsWrapped);
            Assert.IsTrue(viewModel.ChildModelProperty.IsModelProperty);
            Assert.IsFalse(viewModel.ChildModelProperty.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.ChildModelProperty2.IsWrapped);
            Assert.IsFalse(viewModel.ChildModelProperty3.IsWrapped);
            Assert.IsFalse(viewModel.ChildModelProperty4.IsWrapped);
            Assert.IsFalse(viewModel.ChildModelProperty5.IsWrapped);
            Assert.IsFalse(viewModel.ChildCollectionProperty1.IsWrapped);
            Assert.IsFalse(viewModel.ChildCollectionProperty1.IsModelProperty);
            Assert.IsTrue(viewModel.ChildCollectionProperty1.IsModelCollectionProperty);
            Assert.IsFalse(viewModel.ChildCollectionProperty2.IsWrapped);
            Assert.IsFalse(viewModel.ChildCollectionProperty3.IsWrapped);
            Assert.IsFalse(viewModel.ChildCollectionProperty4.IsWrapped);
            Assert.IsFalse(viewModel.ChildCollectionProperty5.IsWrapped);

            Assert.AreEqual(viewModel.ComputedStringProperty.Name, "ComputedStringProperty");
            Assert.AreEqual(viewModel.ComputedStringProperty2.Name, "ComputedStringProperty2");
            Assert.AreEqual(viewModel.ComputedStringProperty3.Name, "ComputedStringProperty3");
            Assert.AreEqual(viewModel.ComputedStringProperty4.Name, "ComputedStringProperty4");
            Assert.AreEqual(viewModel.ComputedStringProperty5.Name, "ComputedStringProperty5");
            Assert.AreEqual(viewModel.ComputedInt32Property.Name, "ComputedInt32Property");
            Assert.AreEqual(viewModel.ComputedInt32Property2.Name, "ComputedInt32Property2");
            Assert.AreEqual(viewModel.ComputedInt32Property3.Name, "ComputedInt32Property3");
            Assert.AreEqual(viewModel.ComputedInt32Property4.Name, "ComputedInt32Property4");
            Assert.AreEqual(viewModel.ComputedInt32Property5.Name, "ComputedInt32Property5");
            Assert.AreEqual(viewModel.StringProperty.Name, "StringProperty");
            Assert.AreEqual(viewModel.StringProperty2.Name, "StringProperty2");
            Assert.AreEqual(viewModel.StringProperty3.Name, "StringProperty3");
            Assert.AreEqual(viewModel.StringProperty4.Name, "StringProperty4");
            Assert.AreEqual(viewModel.StringProperty5.Name, "StringProperty5");
            Assert.AreEqual(viewModel.Int32Property.Name, "Int32Property");
            Assert.AreEqual(viewModel.Int32Property2.Name, "Int32Property2");
            Assert.AreEqual(viewModel.Int32Property3.Name, "Int32Property3");
            Assert.AreEqual(viewModel.Int32Property4.Name, "Int32Property4");
            Assert.AreEqual(viewModel.Int32Property5.Name, "Int32Property5");
            Assert.AreEqual(viewModel.NullableUInt32Property.Name, "NullableUInt32Property");
            Assert.AreEqual(viewModel.NullableUInt32Property2.Name, "NullableUInt32Property2");
            Assert.AreEqual(viewModel.NullableUInt32Property3.Name, "NullableUInt32Property3");
            Assert.AreEqual(viewModel.NullableUInt32Property4.Name, "NullableUInt32Property4");
            Assert.AreEqual(viewModel.NullableUInt32Property5.Name, "NullableUInt32Property5");
            Assert.AreEqual(viewModel.EnumProperty.Name, "EnumProperty");
            Assert.AreEqual(viewModel.EnumProperty2.Name, "EnumProperty2");
            Assert.AreEqual(viewModel.EnumProperty3.Name, "EnumProperty3");
            Assert.AreEqual(viewModel.EnumProperty4.Name, "EnumProperty4");
            Assert.AreEqual(viewModel.EnumProperty5.Name, "EnumProperty5");
            Assert.AreEqual(viewModel.NullableEnumProperty.Name, "NullableEnumProperty");
            Assert.AreEqual(viewModel.NullableEnumProperty2.Name, "NullableEnumProperty2");
            Assert.AreEqual(viewModel.NullableEnumProperty3.Name, "NullableEnumProperty3");
            Assert.AreEqual(viewModel.NullableEnumProperty4.Name, "NullableEnumProperty4");
            Assert.AreEqual(viewModel.NullableEnumProperty5.Name, "NullableEnumProperty5");
            Assert.AreEqual(viewModel.StringArrayProperty.Name, "StringArrayProperty");
            Assert.AreEqual(viewModel.StringArrayProperty2.Name, "StringArrayProperty2");
            Assert.AreEqual(viewModel.StringArrayProperty3.Name, "StringArrayProperty3");
            Assert.AreEqual(viewModel.StringArrayProperty4.Name, "StringArrayProperty4");
            Assert.AreEqual(viewModel.StringArrayProperty5.Name, "StringArrayProperty5");
            Assert.AreEqual(viewModel.EnumerableProperty.Name, "EnumerableProperty");
            Assert.AreEqual(viewModel.EnumerableProperty2.Name, "EnumerableProperty2");
            Assert.AreEqual(viewModel.EnumerableProperty3.Name, "EnumerableProperty3");
            Assert.AreEqual(viewModel.EnumerableProperty4.Name, "EnumerableProperty4");
            Assert.AreEqual(viewModel.EnumerableProperty5.Name, "EnumerableProperty5");
            Assert.AreEqual(viewModel.ChildModelProperty.Name, "ChildModelProperty");
            Assert.AreEqual(viewModel.ChildModelProperty2.Name, "ChildModelProperty2");
            Assert.AreEqual(viewModel.ChildModelProperty3.Name, "ChildModelProperty3");
            Assert.AreEqual(viewModel.ChildModelProperty4.Name, "ChildModelProperty4");
            Assert.AreEqual(viewModel.ChildModelProperty5.Name, "ChildModelProperty5");
            Assert.AreEqual(viewModel.ChildCollectionProperty1.Name, "ChildCollectionProperty1");
            Assert.AreEqual(viewModel.ChildCollectionProperty2.Name, "ChildCollectionProperty2");
            Assert.AreEqual(viewModel.ChildCollectionProperty3.Name, "ChildCollectionProperty3");
            Assert.AreEqual(viewModel.ChildCollectionProperty4.Name, "ChildCollectionProperty4");
            Assert.AreEqual(viewModel.ChildCollectionProperty5.Name, "ChildCollectionProperty5");

            Assert.AreEqual(viewModel.ComputedStringProperty.Behavior, ModelBase.StandardBehaviors.RemoveBehavior(ModelPropertyBehaviors.SetsParentIsDirty));
            Assert.AreEqual(viewModel.ComputedStringProperty2.Behavior, ModelBase.StandardBehaviors.RemoveBehavior(ModelPropertyBehaviors.SetsParentIsDirty));
            Assert.AreEqual(viewModel.ComputedStringProperty3.Behavior, ModelPropertyBehaviors.IsResettable | ModelPropertyBehaviors.SupportsPropertyChangeCounting);
            Assert.AreEqual(viewModel.ComputedStringProperty4.Behavior, ModelPropertyBehaviors.SetsIsDirty);
            Assert.AreEqual(viewModel.ComputedStringProperty5.Behavior, null);
            Assert.AreEqual(viewModel.ComputedInt32Property.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ComputedInt32Property2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ComputedInt32Property3.Behavior, ModelPropertyBehaviors.SetsIsDirty);
            Assert.AreEqual(viewModel.ComputedInt32Property4.Behavior, ModelPropertyBehaviors.SetsIsInvalid);
            Assert.AreEqual(viewModel.ComputedInt32Property5.Behavior, null);
            Assert.AreEqual(viewModel.StringProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.StringProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.StringProperty3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.StringProperty4.Behavior, ModelPropertyBehaviors.IsResettable);
            Assert.AreEqual(viewModel.StringProperty5.Behavior, null);
            Assert.AreEqual(viewModel.Int32Property.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.Int32Property2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.Int32Property3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.Int32Property4.Behavior, ModelPropertyBehaviors.SetsIsDirty);
            Assert.AreEqual(viewModel.Int32Property5.Behavior, null);
            Assert.AreEqual(viewModel.NullableUInt32Property.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableUInt32Property2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableUInt32Property3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableUInt32Property4.Behavior, ModelPropertyBehaviors.SetsIsInvalid);
            Assert.AreEqual(viewModel.NullableUInt32Property5.Behavior, null);
            Assert.AreEqual(viewModel.EnumProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.EnumProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.EnumProperty3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.EnumProperty4.Behavior, ModelPropertyBehaviors.SetsParentIsDirty);
            Assert.AreEqual(viewModel.EnumProperty5.Behavior, null);
            Assert.AreEqual(viewModel.NullableEnumProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableEnumProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableEnumProperty3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.NullableEnumProperty4.Behavior, ModelPropertyBehaviors.SetsParentIsInvalid);
            Assert.AreEqual(viewModel.NullableEnumProperty5.Behavior, null);
            Assert.AreEqual(viewModel.StringArrayProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.StringArrayProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.StringArrayProperty3.Behavior, ModelPropertyBehaviors.SetsParentIsDirty);
            Assert.AreEqual(viewModel.StringArrayProperty4.Behavior, ModelPropertyBehaviors.SetsParentIsDirty | ModelPropertyBehaviors.IsResettable);
            Assert.AreEqual(viewModel.StringArrayProperty5.Behavior, null);
            Assert.AreEqual(viewModel.EnumerableProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.EnumerableProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.EnumerableProperty3.Behavior, ModelPropertyBehaviors.IsResettable);
            Assert.AreEqual(viewModel.EnumerableProperty4.Behavior, ModelPropertyBehaviors.SetsParentIsDirty);
            Assert.AreEqual(viewModel.EnumerableProperty5.Behavior, null);
            Assert.AreEqual(viewModel.ChildModelProperty.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ChildModelProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ChildModelProperty5.Behavior, null);
            Assert.AreEqual(viewModel.ChildCollectionProperty1.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ChildCollectionProperty2.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ChildCollectionProperty3.Behavior, ModelBase.StandardBehaviors);
            Assert.AreEqual(viewModel.ChildCollectionProperty4.Behavior, ModelPropertyBehaviors.SetsIsInvalid);
            Assert.AreEqual(viewModel.ChildCollectionProperty5.Behavior, null);

            Assert.AreEqual(viewModel.Properties.Count(), 58);
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.UnconstrainedInt32));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.UnconstrainedNullableInt32));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedStringProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedStringProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedStringProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedStringProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedStringProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedInt32Property));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedInt32Property2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedInt32Property3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedInt32Property4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ComputedInt32Property5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.Int32Property));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.Int32Property2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.Int32Property3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.Int32Property4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.Int32Property5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableUInt32Property));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableUInt32Property2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableUInt32Property3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableUInt32Property4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableUInt32Property5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableEnumProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableEnumProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableEnumProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableEnumProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.NullableEnumProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringArrayProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringArrayProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringArrayProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringArrayProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.StringArrayProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumerableProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumerableProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumerableProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumerableProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.EnumerableProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildModelProperty));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildModelProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildModelProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildModelProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildModelProperty5));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildCollectionProperty1));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildCollectionProperty2));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildCollectionProperty3));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildCollectionProperty4));
            Assert.IsTrue(viewModel.Properties.Contains(viewModel.ChildCollectionProperty5));

            viewModel.ValidateProperties();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterGenericPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureB>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterCollectionPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureA>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterValueTypePropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureC>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterNullableValueTypePropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureD>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterEnumPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureE>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterNullableEnumPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureF>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterStringPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureG>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterModelChildPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureH>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterUnconstrainedPropertyAfterInitialization()
        {
            Creator.Create<ModelForRegistrationFailureI>().RegisterProperty();
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RegisterNullComputationMethod()
        {
            try
            {
                Creator.Create<ModelForRegistrationFailureK>();
            }
            catch (Exception e)
            {
                throw e.InnerException;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RegisterNullPropertyForComputedProperty()
        {
            try
            {
                Creator.Create<ModelForRegistrationFailureJ>();
            }
            catch (Exception e)
            {
                throw e.InnerException;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RegisterNoPropertiesForComputedProperty()
        {
            try
            {
                Creator.Create<ModelForRegistrationFailureL>();
            }
            catch (Exception e)
            {
                throw e.InnerException;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RegisterForeignPropertiesForComputedProperty()
        {
            try
            {
                Creator.Create<ModelForRegistrationFailureM>();
            }
            catch (Exception e)
            {
                throw e.InnerException;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RegisterModelPropertyForComputedProperty()
        {
            try
            {
                Creator.Create<ModelForRegistrationFailureN>();
            }
            catch (Exception e)
            {
                throw e.InnerException;
            }
        }

        [TestMethod]
        public void ComputedPropertyValueTest1()
        {
            ModelForComputedPropertyTest viewModel = Creator.Create<ModelForComputedPropertyTest>();

            Assert.AreEqual(viewModel.IntPropertyA.Value, viewModel.IntPropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.IntPropertyB.Value, viewModel.IntPropertyB.GetDefaultValue());
            Assert.IsNotNull(viewModel.IntPropertyA.PropertySync);
            Assert.IsNull(viewModel.IntPropertyA.PropertySync.SyncedToProperty);
            Assert.IsNull(viewModel.IntPropertyA.PropertySync.SyncedToPropertyReference);
            Assert.IsFalse(viewModel.IntPropertyA.UpdateSyncOnCommit);

            viewModel.IntPropertyA.Value = 4;
            Assert.AreEqual(viewModel.IntPropertyB.Value, viewModel.IntPropertyA.Value);
            viewModel.IntPropertyB.Value = 5;
            Assert.AreEqual(viewModel.IntPropertyA.Value, 4);
            Assert.AreEqual(viewModel.IntPropertyB.Value, 5);
            viewModel.IntPropertyA.Value = 5;
            Assert.AreEqual(viewModel.IntPropertyB.Value, viewModel.IntPropertyA.Value);
            viewModel.IntPropertyA.Value = 6;
            Assert.AreEqual(viewModel.IntPropertyB.Value, viewModel.IntPropertyA.Value);

            Assert.AreEqual(viewModel.DoublePropertyA.Value, viewModel.DoublePropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.DoublePropertyB.Value, viewModel.DoublePropertyB.GetDefaultValue());
            Assert.IsNotNull(viewModel.DoublePropertyA.PropertySync);
            Assert.IsNull(viewModel.DoublePropertyA.PropertySync.SyncedToProperty);
            Assert.IsNull(viewModel.DoublePropertyA.PropertySync.SyncedToPropertyReference);
            Assert.IsFalse(viewModel.DoublePropertyA.UpdateSyncOnCommit);

            viewModel.DoublePropertyA.Value = 4;
            Assert.AreEqual(viewModel.DoublePropertyB.Value, viewModel.DoublePropertyA.Value);
            viewModel.DoublePropertyB.Value = 5;
            Assert.AreEqual(viewModel.DoublePropertyA.Value, 4);
            Assert.AreEqual(viewModel.DoublePropertyB.Value, 5);
            viewModel.DoublePropertyA.Value = 5;
            Assert.AreEqual(viewModel.DoublePropertyB.Value, viewModel.DoublePropertyA.Value);
            viewModel.DoublePropertyA.Value = null;
            Assert.AreEqual(viewModel.DoublePropertyB.Value, viewModel.DoublePropertyA.Value);

            Assert.AreEqual(viewModel.StringPropertyA.Value, viewModel.StringPropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyB.GetDefaultValue());
            Assert.IsNotNull(viewModel.StringPropertyA.PropertySync);
            Assert.IsNull(viewModel.StringPropertyA.PropertySync.SyncedToProperty);
            Assert.IsNull(viewModel.StringPropertyA.PropertySync.SyncedToPropertyReference);
            Assert.IsFalse(viewModel.StringPropertyA.UpdateSyncOnCommit);

            viewModel.StringPropertyA.Value = "4";
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyA.Value);
            viewModel.StringPropertyB.Value = "5";
            Assert.AreEqual(viewModel.StringPropertyA.Value, "4");
            Assert.AreEqual(viewModel.StringPropertyB.Value, "5");
            viewModel.StringPropertyA.Value = "5";
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyA.Value);
            viewModel.StringPropertyA.Value = null;
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyA.Value);
            viewModel.StringPropertyA.Value = String.Empty;
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyA.Value);
            viewModel.StringPropertyA.Value = null;
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyA.Value);

            Assert.AreEqual(viewModel.ObjectPropertyA.Value, viewModel.ObjectPropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.ObjectPropertyB.Value, viewModel.ObjectPropertyB.GetDefaultValue());
            Assert.IsNotNull(viewModel.ObjectPropertyA.PropertySync);
            Assert.IsNull(viewModel.ObjectPropertyA.PropertySync.SyncedToProperty);
            Assert.IsNull(viewModel.ObjectPropertyA.PropertySync.SyncedToPropertyReference);
            Assert.IsFalse(viewModel.ObjectPropertyA.UpdateSyncOnCommit);

            Object valueA = new Object();
            Object valueB = new Object();
            viewModel.ObjectPropertyA.Value = valueA;
            Assert.AreEqual(viewModel.ObjectPropertyB.Value, viewModel.ObjectPropertyA.Value);
            viewModel.ObjectPropertyB.Value = valueB;
            Assert.AreEqual(viewModel.ObjectPropertyA.Value, valueA);
            Assert.AreEqual(viewModel.ObjectPropertyB.Value, valueB);
            viewModel.ObjectPropertyA.Value = valueB;
            Assert.AreEqual(viewModel.ObjectPropertyB.Value, viewModel.ObjectPropertyA.Value);
            viewModel.ObjectPropertyA.Value = null;
            Assert.AreEqual(viewModel.ObjectPropertyB.Value, viewModel.ObjectPropertyA.Value);

            viewModel.StringPropertyA.Reset();
            viewModel.StringPropertyA.UpdateSyncOnCommit = true;
            Assert.AreEqual(viewModel.StringPropertyA.Value, viewModel.StringPropertyB.Value);
            viewModel.StringPropertyA.Value = "Value";
            Assert.AreEqual(viewModel.StringPropertyA.Value, "Value");
            Assert.AreEqual(viewModel.StringPropertyB.Value, viewModel.StringPropertyB.GetDefaultValue());
            viewModel.StringPropertyB.Value = "SomeOtherValue";
            Assert.AreEqual(viewModel.StringPropertyA.Value, "Value");
            Assert.AreEqual(viewModel.StringPropertyB.Value, "SomeOtherValue");
            viewModel.StringPropertyA.Commit();
            Assert.AreEqual(viewModel.StringPropertyA.Value, viewModel.StringPropertyB.Value);
        }

        [TestMethod]
        public void ComputedPropertyValueTest2()
        {
            ModelForComputedPropertyTestB viewModel = Creator.Create<ModelForComputedPropertyTestB>();
            Assert.IsTrue(viewModel.PropertyAInt32.Value == (Int32)viewModel.PropertyADecimal.Value);
            Assert.IsTrue(Object.ReferenceEquals(viewModel.PropertyBString.Value, viewModel.PropertyBObject.Value));
            Assert.IsTrue(viewModel.PropertyCDateTime.Value.Year == 2000);

            viewModel.PropertyAInt32.Value = 45;
            Assert.IsTrue(viewModel.PropertyAInt32.Value == (Int32)viewModel.PropertyADecimal.Value);
            viewModel.PropertyADecimal.Value = null;
            Assert.AreEqual(viewModel.PropertyAInt32.Value, 45);
            Assert.IsNull(viewModel.PropertyADecimal.Value);

            viewModel.PropertyBObject.Value = 6;
            Assert.AreEqual(viewModel.PropertyBObject.Value, 6);
            Assert.AreEqual(viewModel.PropertyBString.Value, null);
            viewModel.PropertyBString.Value = "A value";
            Assert.AreEqual(viewModel.PropertyBString.Value, viewModel.PropertyBObject.Value);

            viewModel.PropertyCDouble.Value = 4;
            Assert.IsTrue(viewModel.PropertyCDateTime.Value.Year == 2004);
            DateTime now = DateTime.Now;
            viewModel.PropertyCDateTime.Value = now;
            Assert.AreEqual(viewModel.PropertyCDateTime.Value, now);
            Assert.AreEqual(viewModel.PropertyCDouble.Value, 4);
        }

        [TestMethod]
        public void ComputedPropertyValueTest3()
        {
            ModelForComputedPropertyTestC viewModel = Creator.Create<ModelForComputedPropertyTestC>();
            Assert.IsNull(viewModel.FirstThreeOfSocial.Value);
            Assert.IsNull(viewModel.MiddleTwoOfSocial.Value);
            Assert.IsNull(viewModel.LastFourOfSocial.Value);
            Assert.AreEqual(viewModel.SocialSecurityNumber.Value, "--");

            viewModel.FirstThreeOfSocial.Value = 123;
            viewModel.MiddleTwoOfSocial.Value = 45;
            viewModel.LastFourOfSocial.Value = 6789;

            Assert.AreEqual(viewModel.SocialSecurityNumber.Value, "123-45-6789");
            viewModel.SocialSecurityNumber.Value = "<Please Enter SSA>";
            Assert.AreEqual(viewModel.FirstThreeOfSocial.Value, 123);
            Assert.AreEqual(viewModel.MiddleTwoOfSocial.Value, 45);
            Assert.AreEqual(viewModel.LastFourOfSocial.Value, 6789);
            Assert.AreEqual(viewModel.SocialSecurityNumber.Value, "<Please Enter SSA>");

            viewModel.FirstThreeOfSocial.Value = 888;
            Assert.AreEqual(viewModel.SocialSecurityNumber.Value, "888-45-6789");

            Assert.AreEqual(viewModel.PropertyA.Value, viewModel.PropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.PropertyB.Value, "B - ");
            Assert.AreEqual(viewModel.PropertyC.Value, "C - B - ");

            viewModel.PropertyB.Value = "BValue";

            Assert.AreEqual(viewModel.PropertyA.Value, viewModel.PropertyA.GetDefaultValue());
            Assert.AreEqual(viewModel.PropertyB.Value, "BValue");
            Assert.AreEqual(viewModel.PropertyC.Value, "C - BValue");

            viewModel.PropertyA.Value = "AValue";

            Assert.AreEqual(viewModel.PropertyA.Value, "AValue");
            Assert.AreEqual(viewModel.PropertyB.Value, "B - AValue");
            Assert.AreEqual(viewModel.PropertyC.Value, "C - B - AValue");
        }

        [TestMethod]
        public void PropertySyncTest()
        {
            ModelForPropertySyncTesting viewModelA = Creator.Create<ModelForPropertySyncTesting>();
            ModelForPropertySyncTesting viewModelB = Creator.Create<ModelForPropertySyncTesting>();

            Assert.IsTrue(viewModelB.StringProperty.AllowSync);
            viewModelA.StringProperty.SyncTo(viewModelB.StringProperty);

            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelA.StringProperty.GetDefaultValue());
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelA.StringProperty.GetDefaultValue());

            viewModelA.StringProperty.Value = "Value";
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelB.StringProperty.Value = "Value";
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelB.StringProperty.Value = "AnotherValue";
            Assert.AreEqual(viewModelA.StringProperty.Value, "Value");
            Assert.AreEqual(viewModelB.StringProperty.Value, "AnotherValue");

            viewModelA.StringProperty.Reset();
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelA.StringProperty.GetDefaultValue());
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.ForceSync();
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.Value = "ValueB";
            viewModelB.StringProperty.Value = "ValueC";
            viewModelA.StringProperty.ForceSync();
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueB");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.Value = "ValueD";
            viewModelB.StringProperty.Value = "ValueE";
            viewModelA.StringProperty.ForceSync(true);
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueD");
            Assert.AreEqual(viewModelB.StringProperty.Value, "ValueE");

            viewModelA.StringProperty.ForceSync(false);
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueD");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.UpdateSyncOnCommit = true;
            viewModelA.StringProperty.Value = "ValueF";
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueF");
            Assert.AreEqual(viewModelB.StringProperty.Value, "ValueD");

            viewModelA.StringProperty.Commit();
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueF");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.Value = "ValueH";
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueH");
            Assert.AreEqual(viewModelB.StringProperty.Value, "ValueF");

            viewModelA.StringProperty.ForceSync();
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueH");
            Assert.AreEqual(viewModelB.StringProperty.Value, "ValueF");

            viewModelA.StringProperty.ForceSync(false);
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueH");
            Assert.AreEqual(viewModelB.StringProperty.Value, "ValueF");

            viewModelA.StringProperty.ForceSync(true);
            Assert.AreEqual(viewModelA.StringProperty.Value, "ValueH");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelA.StringProperty.PropertySync = null;
            viewModelA.StringProperty.ForceSync();

            viewModelA.StringProperty.SyncTo(viewModelA.StringProperty2);
            viewModelA.StringProperty.Value = "NewValue";
            Assert.AreEqual(viewModelA.StringProperty.Value, "NewValue");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelA.StringProperty2.Value);

            viewModelA.StringProperty2.AllowSync = false;
            viewModelA.StringProperty.Value = "AnotherValue";
            Assert.AreEqual(viewModelA.StringProperty.Value, "AnotherValue");
            Assert.AreEqual(viewModelA.StringProperty2.Value, "NewValue");

            viewModelA.IntProperty.Value = 45;
            viewModelA.IntProperty.SyncTo(viewModelB.IntProperty);
            Assert.IsFalse(viewModelA.IntProperty.UpdateSyncOnCommit);
            Assert.AreEqual(viewModelA.IntProperty.Value, 45);
            Assert.AreEqual(viewModelA.IntProperty.Value, viewModelB.IntProperty.Value);

            viewModelA.DecimalProperty.Value = 34;
            viewModelA.DecimalProperty.SyncTo(viewModelB.DecimalProperty, true);
            Assert.IsTrue(viewModelA.DecimalProperty.UpdateSyncOnCommit);
            Assert.AreEqual(viewModelA.DecimalProperty.Value, 34);
            Assert.AreEqual(viewModelA.DecimalProperty.Value, viewModelB.DecimalProperty.Value);

            viewModelA.EnumProperty.Value = EnumForTesting.TestValue2;
            viewModelA.EnumProperty.SyncTo(viewModelB.EnumProperty, false);
            Assert.IsFalse(viewModelA.EnumProperty.UpdateSyncOnCommit);
            Assert.AreEqual(viewModelA.EnumProperty.Value, EnumForTesting.TestValue2);
            Assert.AreEqual(viewModelA.EnumProperty.Value, viewModelB.EnumProperty.Value);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SyncToNullPropertyTest()
        {
            ModelForPropertySyncTesting viewModel = Creator.Create<ModelForPropertySyncTesting>();
            viewModel.StringProperty.SyncTo(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void PropertySyncNullPropertyTest2()
        {
            ModelForPropertySyncTesting viewModel = Creator.Create<ModelForPropertySyncTesting>();
            viewModel.StringProperty.PropertySync = new PropertySync<String>(null, null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void SyncToSelfPropertyTest()
        {
            ModelForPropertySyncTesting viewModel = Creator.Create<ModelForPropertySyncTesting>();
            viewModel.StringProperty.SyncTo(viewModel.StringProperty);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void CyclicalSyncPropertyTest()
        {
            ModelForPropertySyncTesting viewModel = Creator.Create<ModelForPropertySyncTesting>();
            viewModel.StringProperty.SyncTo(viewModel.StringProperty2);
            viewModel.StringProperty2.SyncTo(viewModel.StringProperty);
        }

        [TestMethod]
        public void PropertySyncHardReferenceTest()
        {
            ModelForPropertySyncTesting viewModelA = Creator.Create<ModelForPropertySyncTesting>();
            ModelForPropertySyncTesting viewModelB = Creator.Create<ModelForPropertySyncTesting>();
            Int32 viewModelBHashCode = viewModelB.StringProperty.GetHashCode();

            viewModelA.StringProperty.PropertySync = new PropertySync<String>(viewModelA.StringProperty, viewModelB.StringProperty, false, true);
            Assert.AreEqual(viewModelA.StringProperty.PropertySync.SyncedToProperty, viewModelB.StringProperty);
            Assert.IsNull(viewModelA.StringProperty.PropertySync.SyncedToPropertyReference);

            viewModelA.StringProperty.Value = "Value";
            Assert.AreEqual(viewModelA.StringProperty.Value, "Value");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelB.StringProperty.AllowSync = false;
            viewModelA.StringProperty.Value = "AnotherValue";
            Assert.AreEqual(viewModelA.StringProperty.Value, "AnotherValue");
            Assert.AreEqual(viewModelB.StringProperty.Value, "Value");

            viewModelB = null;

            GC.Collect(2);
            GC.WaitForPendingFinalizers();

            Assert.IsNotNull(viewModelA.StringProperty.PropertySync.SyncedToProperty);
            Assert.IsNull(viewModelA.StringProperty.PropertySync.SyncedToPropertyReference);
            Assert.AreEqual(viewModelA.StringProperty.PropertySync.SyncedToProperty.GetHashCode(), viewModelBHashCode);
        }

        [TestMethod]
        public void PropertySyncSoftReferenceTest()
        {
            ModelForPropertySyncTesting viewModelA = Creator.Create<ModelForPropertySyncTesting>();
            ModelForPropertySyncTesting viewModelB = Creator.Create<ModelForPropertySyncTesting>();

            viewModelA.StringProperty.PropertySync = new PropertySync<String>(viewModelA.StringProperty, viewModelB.StringProperty, false, false);
            Assert.AreEqual(viewModelA.StringProperty.PropertySync.SyncedToPropertyReference.Target, viewModelB.StringProperty);
            Assert.IsNull(viewModelA.StringProperty.PropertySync.SyncedToProperty);

            viewModelA.StringProperty.Value = "Value";
            Assert.AreEqual(viewModelA.StringProperty.Value, "Value");
            Assert.AreEqual(viewModelA.StringProperty.Value, viewModelB.StringProperty.Value);

            viewModelB = null;

            GC.Collect(GC.MaxGeneration);
            GC.WaitForPendingFinalizers();

            Assert.IsNull(viewModelA.StringProperty.PropertySync.SyncedToProperty);
            Assert.IsNotNull(viewModelA.StringProperty.PropertySync.SyncedToPropertyReference);
            Assert.IsNull(viewModelA.StringProperty.PropertySync.SyncedToPropertyReference.Target);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void PropertySyncModelTest()
        {
            ModelForPropertySyncTestingB viewModel = Creator.Create<ModelForPropertySyncTestingB>();
            viewModel.Property1.SyncTo(viewModel.Property2);
        }

        [TestMethod]
        public void PropertySyncUnconstrainedPropertyTest()
        {
            ModelForPropertySyncTestingB viewModel = Creator.Create<ModelForPropertySyncTestingB>();

            viewModel.Property3.Value = new Object();
            viewModel.Property3.SyncTo(viewModel.Property4);
            Assert.AreEqual(viewModel.Property3.Value, viewModel.Property4.Value);
            viewModel.Property3.Value = new Object();
            Assert.AreEqual(viewModel.Property3.Value, viewModel.Property4.Value);
        }
    }
}
